package com.uatair.common.tcp.client;

import com.google.protobuf.CodedInputStream;
import com.uatair.common.config.TcpClientConfig;
import com.uatair.common.tcp.util.ProtocolConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

@Component
public class TcpClientService {
    private static final Logger log = LoggerFactory.getLogger(TcpClientService.class);

    @Autowired
    private TcpClientConfig config;

    private Socket socket;
    private OutputStream outputStream;
    private InputStream inputStream;
    private ExecutorService executorService;
    private volatile boolean running = false;
    private final ReentrantLock lock = new ReentrantLock();

    /**
     * 初始化TCP连接并启动消息监听线程
     */
//    @PostConstruct
    public void init() {
        try {
            if (config == null) {
                throw new IllegalStateException("TcpClientConfig 未正确注入");
            }

            log.info("正在连接TCP服务器 {}:{}", config.getHost(), config.getPort());
            executorService = Executors.newSingleThreadExecutor();
            connect();
            log.info("TCP客户端初始化成功");
        } catch (Exception e) {
            log.error("TCP客户端初始化失败", e);
            throw new RuntimeException("TCP客户端初始化失败", e);
        }
    }

    /**
     * 建立TCP连接
     */
    public void connect() {
        try {
            socket = new Socket();
            socket.connect(new InetSocketAddress(config.getHost(), config.getPort()), 5000);
            socket.setSoTimeout(5000);
            socket.setKeepAlive(true);
            socket.setTcpNoDelay(true);
            outputStream = socket.getOutputStream();
            inputStream = socket.getInputStream();
            running = true;
            log.info("TCP客户端连接成功，服务器地址: {}:{}", config.getHost(), config.getPort());
        } catch (IOException e) {
            log.error("TCP客户端连接失败", e);
        }
    }

    /**
     * 发送消息
     *
     * @param message 要发送的消息
     * @return 是否发送成功
     */
    public void sendMessage(byte[] message) {
        if (socket == null || !socket.isConnected()) {
            log.error("TCP连接未建立或已断开");
        }
        try {
            String upperCase = new BigInteger(1, message).toString(16).toUpperCase();
            outputStream.write(hexStringToByteArray(upperCase));
            outputStream.flush();
            log.info("消息发送成功: {}", upperCase);

            byte[] tempBuffer = new byte[45]; // 假设前2字节是消息头
            int bytesRead = inputStream.read(tempBuffer);
            if (bytesRead == -1) {
                log.error("");
            }
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            buffer.write(tempBuffer, 0, bytesRead);

            // 检查是否收到完整消息（根据0x7E结束标志）
            byte[] receivedData = buffer.toByteArray();
            String hexString = new BigInteger(1, receivedData).toString(16).toUpperCase();
            // 确保十六进制字符串长度为偶数
            if (hexString.length() % 2 != 0) {
                hexString = "0" + hexString;
            }
            log.info("十六进制格式: {}", hexString);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 启动消息接收线程
     */
    private void startMessageReceiver() {
        executorService.execute(this::handleServerResponses);
    }

    // 将HEX字符串转换为字节数组的方法
    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

    private void handleServerResponses() {
        while (running) {
            try {
                byte[] tempBuffer = new byte[45]; // 假设前2字节是消息头
                int bytesRead = inputStream.read(tempBuffer);
                if (bytesRead == -1) {
                    log.error("");
                }
                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                buffer.write(tempBuffer, 0, bytesRead);

                // 检查是否收到完整消息（根据0x7E结束标志）
                byte[] receivedData = buffer.toByteArray();
                String hexString = new BigInteger(1, receivedData).toString(16).toUpperCase();
                // 确保十六进制字符串长度为偶数
                if (hexString.length() % 2 != 0) {
                    hexString = "0" + hexString;
                }
                log.info("接收服务器响应: {}", hexString);

            } catch (SocketTimeoutException e) {
                System.out.println("等待服务器响应超时");
            } catch (IOException e) {
                log.error("响应处理", e);
            }
        }
    }

    /**
     * 重连机制
     */
    private void reconnect() {
        closeResources();
        int retry = 0;
        int maxRetries = 3;
        long retryInterval = 5000; // 5秒

        while (retry < maxRetries && running) {
            try {
                Thread.sleep(retryInterval);
                log.info("尝试重新连接({}/{})...", retry + 1, maxRetries);
                connect();
                if (socket != null && socket.isConnected()) {
//                    startMessageReceiver();
                    log.info("重连成功");
                    return; // 重连成功
                }
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                return;
            } catch (Exception e) {
                log.error("重连失败", e);
            }
            retry++;
        }

        if (running) {
            log.error("达到最大重试次数，停止重连");
            running = false;
        }
    }

    /**
     * 关闭资源
     */
    private void closeResources() {
        try {
            /*if (outputStream != null) {
                outputStream.close();
            }
            if (reader != null) {
                reader.close();
            }*/
            if (socket != null) {
                socket.close();
            }
        } catch (IOException e) {
            log.error("关闭资源时发生错误", e);
        }
    }

    /**
     * 关闭连接
     */
    @PreDestroy
    public void close() {
        running = false;
        if (executorService != null) {
            executorService.shutdownNow();
        }
        closeResources();
        log.info("TCP客户端已关闭");
    }
}
